using System.Collections.Generic;
using System.IO;

namespace OracleInternal.Sharding
{
	internal class Chunk
	{
		internal class Metadata
		{
			internal string ChunkName
			{
				get;
				set;
			}

			internal Stream ShardKeyLow
			{
				get;
				set;
			}

			internal Stream ShardKeyHigh
			{
				get;
				set;
			}

			internal Stream GroupKeyLow
			{
				get;
				set;
			}

			internal Stream GroupKeyHigh
			{
				get;
				set;
			}

			internal int Priority
			{
				get;
				set;
			}

			internal int ChunkId
			{
				get;
				set;
			}

			internal int ChunkUniqueId
			{
				get;
				set;
			}

			internal string ShardName
			{
				get;
				set;
			}

			internal ChunkStatus Status
			{
				get;
				set;
			}

			internal Metadata()
			{
			}
		}

		private SortedDictionary<int, HashSet<string>> instancesByPriority = new SortedDictionary<int, HashSet<string>>();

		private SortedDictionary<string, int> priorityByInstances = new SortedDictionary<string, int>();

		private SortedDictionary<ChunkStatus, HashSet<string>> instancesByStatus = new SortedDictionary<ChunkStatus, HashSet<string>>();

		private SortedDictionary<string, ChunkStatus> statusByInstances = new SortedDictionary<string, ChunkStatus>();

		private HashSet<string> allInstances = new HashSet<string>();

		internal string Name
		{
			get;
			set;
		}

		internal string AbsoluteName
		{
			get
			{
				if (Name == null)
				{
					return Name;
				}
				int num = Name.IndexOf("-");
				if (-1 != num)
				{
					return Name.Substring(0, num);
				}
				return Name;
			}
		}

		internal int Id
		{
			get;
			set;
		}

		internal int UniqueId
		{
			get;
			set;
		}

		internal HashSet<string> AllInstances => allInstances;

		internal HashSet<string> HighestPriorityInstances
		{
			get
			{
				if (instancesByPriority.Count > 0)
				{
					IEnumerator<KeyValuePair<int, HashSet<string>>> enumerator = instancesByPriority.GetEnumerator();
					if (enumerator.MoveNext())
					{
						return enumerator.Current.Value;
					}
				}
				return new HashSet<string>();
			}
		}

		internal List<string> AllHighestPriorityInstances
		{
			get
			{
				List<string> list = new List<string>();
				foreach (KeyValuePair<int, HashSet<string>> item in instancesByPriority)
				{
					list.AddRange(item.Value);
				}
				return list;
			}
		}

		internal Chunk(string name)
		{
			Name = name;
			Id = 0;
			UniqueId = 0;
		}

		internal bool HasInstance(string instance)
		{
			if (priorityByInstances.ContainsKey(instance))
			{
				return true;
			}
			return false;
		}

		internal int GetInstancePriority(string instance)
		{
			return priorityByInstances[instance];
		}

		internal ChunkStatus GetInstanceStatus(string instance)
		{
			return statusByInstances[instance];
		}

		internal void SetInstanceStatus(string instance, ChunkStatus newStatus)
		{
			RemoveInstanceStatus(instance);
			AddInstanceStatus(instance, newStatus);
		}

		internal void AddInstance(string instance, int priority, ChunkStatus status)
		{
			RemoveInstance(instance);
			HashSet<string> hashSet = null;
			try
			{
				hashSet = instancesByPriority[priority];
			}
			catch (KeyNotFoundException)
			{
				hashSet = new HashSet<string>();
				instancesByPriority.Add(priority, hashSet);
			}
			hashSet.Add(instance);
			priorityByInstances.Add(instance, priority);
			try
			{
				hashSet = instancesByStatus[status];
			}
			catch (KeyNotFoundException)
			{
				hashSet = new HashSet<string>();
				instancesByStatus.Add(status, hashSet);
			}
			hashSet.Add(instance);
			statusByInstances.Add(instance, status);
			allInstances.Add(instance);
		}

		internal bool RemoveInstance(string instance)
		{
			int num = 0;
			ChunkStatus chunkStatus = ChunkStatus.Up;
			try
			{
				num = priorityByInstances[instance];
				chunkStatus = statusByInstances[instance];
			}
			catch (KeyNotFoundException)
			{
				return false;
			}
			priorityByInstances.Remove(instance);
			statusByInstances.Remove(instance);
			try
			{
				HashSet<string> hashSet = instancesByPriority[num];
				hashSet.Remove(instance);
				if (hashSet.Count == 0)
				{
					instancesByPriority.Remove(num);
				}
			}
			catch (KeyNotFoundException)
			{
			}
			try
			{
				HashSet<string> hashSet2 = instancesByStatus[chunkStatus];
				hashSet2.Remove(instance);
				if (hashSet2.Count == 0)
				{
					instancesByStatus.Remove(chunkStatus);
				}
			}
			catch (KeyNotFoundException)
			{
			}
			allInstances.Remove(instance);
			return true;
		}

		private void AddInstanceStatus(string instance, ChunkStatus status)
		{
			HashSet<string> hashSet = null;
			try
			{
				hashSet = instancesByStatus[status];
			}
			catch (KeyNotFoundException)
			{
				hashSet = new HashSet<string>();
				instancesByStatus.Add(status, hashSet);
			}
			hashSet.Add(instance);
			statusByInstances.Add(instance, status);
		}

		private bool RemoveInstanceStatus(string instance)
		{
			ChunkStatus chunkStatus = ChunkStatus.Up;
			try
			{
				chunkStatus = statusByInstances[instance];
			}
			catch (KeyNotFoundException)
			{
				return false;
			}
			statusByInstances.Remove(instance);
			try
			{
				HashSet<string> hashSet = instancesByStatus[chunkStatus];
				hashSet.Remove(instance);
				if (hashSet.Count == 0)
				{
					instancesByStatus.Remove(chunkStatus);
				}
			}
			catch (KeyNotFoundException)
			{
			}
			return true;
		}
	}
}
